﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Mr.LinqToWeibo.SearchCriteria;

namespace Mr.LinqToWeibo
{
	internal static class WeiboApiFactory
	{
		public static WeiboApi FRIENDS_TIMELINE {
			get {
				WeiboApi api = new WeiboApi (
                    c => WeiboApiConstants.FRIENDS_TIMELINE,
                    NewKeyValue<ISearchCriteria> ("count", s => s.Count.ToString()),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
                    NewKeyValue<ISearchCriteria> ("feature", s => (int)s.Feature + string.Empty),
                    NewKeyValue<ISearchCriteria> ("base_app", s => (s.BaseApp ? 1 : 0) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
                    );

				return api;
			}
		}
		
		public static WeiboApi PUBLIC_TIMELINE {
			get {
				WeiboApi api = new WeiboApi (
                    c => WeiboApiConstants.PUBLIC_TIMELINE,
                    NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("base_app", s => (s.BaseApp ? 1 : 0) + string.Empty)
                    );

				return api;
			}
		}
		
		public static WeiboApi MENTIONS {
			get {
				WeiboApi api = new WeiboApi (
                    c => WeiboApiConstants.MENTIONS,
                    NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
                    );

				return api;
			}
		}
		
		public static WeiboApi USER_TIMELINE {
			get {
				WeiboApi api = new WeiboApi (
                    s => {
					if (s.UserId <= 0) {
						throw new ArgumentException ("User.Id must be set when invoking USER_TIMELINE api.");
					}
					return string.Format (WeiboApiConstants.USER_TIMELINE_FORMAT, s.UserId);
				}, 
                    NewKeyValue<ISearchCriteria> ("id", // user id
					s => {
					if (s.UserId <= 0) {
						throw new ArgumentNullException ("User.Id must be set when invoking repost_timeline api");
					}
					return s.UserId.ToString ();
				}),
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty),
					NewKeyValue<ISearchCriteria> ("feature", s => (int)s.Feature + string.Empty),
                    NewKeyValue<ISearchCriteria> ("base_app", s => (s.BaseApp ? 1 : 0) + string.Empty)
                    );

				return api;
			}	
		}
		
		public static WeiboApi REPOST_TIMELINE {
			get {
				WeiboApi api = new WeiboApi (
                    c => WeiboApiConstants.REPOST_TIMELINE,
                    NewKeyValue<ISearchCriteria> ("id", // Weibo id
					s => {
					if (s.Id <= 0) {
						throw new ArgumentException ("Weibo.Id must be set when invoking repost_timeline api");
					}
					return s.Id.ToString ();
				}),
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
                    );

				return api;
			}			
		}
		
		public static WeiboApi REPOST_BY_ME {
			get {
				WeiboApi api = new WeiboApi (
					c => WeiboApiConstants.REPOST_BY_ME,
                    NewKeyValue<ISearchCriteria> ("id", 
					s => {
					if (s.UserId <= 0) {
						throw new ArgumentException ("Weibo.Id must be set when invoking repost_timeline api");
					}
					return s.UserId.ToString ();
				}),
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty));

				return api;
			}
		}
		
		public static WeiboApi COMMENTS_TIMELINE {
			get {
				WeiboApi api = new WeiboApi (
					c => WeiboApiConstants.COMMENTS_TIMELINE,
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
					);
				return api;
			}
		}
		
		public static WeiboApi COMMENTS_BY_ME {
			get {
				WeiboApi api = new WeiboApi (
					c => WeiboApiConstants.COMMENTS_BY_ME,
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
					);
				return api;
			}
		}
		
		public static WeiboApi COMMENTS_TO_ME {
			get {
				WeiboApi api = new WeiboApi (
					c => WeiboApiConstants.COMMENTS_TO_ME,
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
					);
				return api;
			}
		}
		
		public static WeiboApi COMMENTS_FOR_ONE_WEIBO {
			get {
				WeiboApi api = new WeiboApi (
					c => WeiboApiConstants.COMMENTS_FOR_ONE_WEIBO,
					NewKeyValue<ISearchCriteria> ("id", s => // weibo id
				{
					if (s.Id <= 0) {
						throw new ArgumentException ("Comment.Weibo.Id must be set when invoking comments for one weibo api.");
					}
					return s.Id.ToString ();
				}),
					NewKeyValue<ISearchCriteria> ("count", s => s.Count + string.Empty),
                    NewKeyValue<ISearchCriteria> ("page", s => s.PageIndex + string.Empty),
					NewKeyValue<ISearchCriteria> ("max_id", s => (s.MaxId > 0 ? s.MaxId : long.MaxValue) + string.Empty),
                    NewKeyValue<ISearchCriteria> ("since_id", s => (s.SinceId > 0 ? s.SinceId : 0) + string.Empty)
					);
				return api;
			}
		}
		
		public static WeiboApi WEIBO_FOR_ONE_TRENDS {
			get {
				WeiboApi api = new WeiboApi (
					c => WeiboApiConstants.WEIBO_FOR_ONE_TRENDS,
					NewKeyValue<ISearchCriteria> ("trend_name", s =>
				{
					if (string.IsNullOrEmpty (s.TrendKeyWord)) {
						throw new ArgumentException ("Weibo.Trend.KeyWord must be set when invoking weibos for one trend api.");
					}
					return s.TrendKeyWord;
				})
					);
				return api;
			}
		}

		private static KeyValuePair<string, Func<TCriteria, string>>
            NewKeyValue<TCriteria> (string name, Func<TCriteria, string> func)
		{
			return new KeyValuePair<string, Func<TCriteria, string>> (name, func);
		}
	}
}
